// bdlt_timetableloader.h                                             -*-C++-*-
#ifndef INCLUDED_BDLT_TIMETABLELOADER
#define INCLUDED_BDLT_TIMETABLELOADER

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide a protocol (or pure interface) for loading timetables.
//
//@CLASSES:
//  bdlt::TimetableLoader: pure interface for loading timetables
//
//@SEE_ALSO: bdlt_timetablecache, bdlt_timetable
//
//@DESCRIPTION: This component provides a protocol, 'bdlt::TimetableLoader',
// for loading timetables from a specific source.  Each repository of timetable
// information can be supported by a distinct implementation of the
// 'TimetableLoader' protocol.  The protocol's primary method, 'load', loads a
// timetable into a 'bdlt::Timetable' object.  The timetable to load is
// identified by name, which is specified by a null-terminated C-style string
// (i.e., 'const char *').
//
///Thread Safety
///-------------
// Unless otherwise documented, a single timetable loader object is not safe
// for concurrent access by multiple threads.  Classes derived from
// 'bdlt::TimetableLoader' that are specifically designed for concurrent access
// must be documented as such.  Unless specifically documented otherwise,
// separate objects of classes derived from 'bdlt::TimetableLoader' may safely
// be used in separate threads.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Implementing the 'bdlt::TimetableLoader' Protocol
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// This example demonstrates an elided concrete implementation of the
// 'bdlt::TimetableLoader' protocol that interprets timetable information
// contained in ASCII strings that are formatted using JSON.  Note that, in
// general, an implementation of 'bdlt::TimetableLoader' must obtain timetable
// information from *some* data source.  Our elided implementation leaves it
// unspecified as to where the JSON strings are obtained (i.e., whether from a
// file system, a database, a local or remote service, etc.).
//
// First, we show the JSON format that our timetable loader accepts:
//..
//  {
//      "firstDate":             "YYYY-MM-DD",
//      "lastDate":              "YYYY-MM-DD",
//      "initialTransitionCode": code,
//      "transitions":
//        [
//          {
//            "datetime": "YYYY-MM-DDThh:mm:ss",
//            "code":     code
//          }
//        ]
//  }
//..
// Note that "YYYY-MM-DD" is an ISO 8601 representation for the value of a
// 'bdlt::Date' object, "YYYY-MM-DDThh:mm:ss" is an ISO 8601 representation for
// the value of a 'bdlt::Datetime' object, and 'code' is an integer greater
// than or equal to -1 (with -1 used to specify
// 'bdlt::Timetable::k_UNSET_TRANSITION_CODE').  We assume that the four JSON
// attributes, "firstDate", "lastDate", "initialTransitionCode", and
// "transitions", must occur in the JSON string in the order in which they
// appear in the above display, but only "firstDate" and "lastDate" are
// *required* attributes.
//
// Then, we define the interface of our implementation:
//..
//  class MyTimetableLoader : public bdlt::TimetableLoader {
//      // This class provides a concrete implementation of the
//      // 'bdlt::TimetableLoader' protocol (an abstract interface) for loading
//      // a timetable.  This elided implementation obtains timetable
//      // information from ASCII strings formatted using JSON.  The source of
//      // the strings is unspecified.
//
//    public:
//      // CREATORS
//      MyTimetableLoader();
//          // Create a 'MyTimetableLoader' object.
//
//      virtual ~MyTimetableLoader();
//          // Destroy this object.
//
//      // MANIPULATORS
//      virtual int load(bdlt::Timetable *result, const char *timetableName);
//          // Load, into the specified 'result', the timetable identified by
//          // the specified 'timetableName'.  Return 0 on success, and a
//          // non-zero value otherwise.  If the timetable corresponding to
//          // 'timetableName' is not found, 1 is returned with no effect on
//          // '*result'.  If a non-zero value other than 1 is returned
//          // (indicating a different error), '*result' is valid, but its
//          // value is undefined.
//  };
//..
// Next, we implement the creators, trivially, as 'MyTimetableLoader' does not
// contain any instance data members:
//..
//  // CREATORS
//  inline
//  MyTimetableLoader::MyTimetableLoader()
//  {
//  }
//
//  inline
//  MyTimetableLoader::~MyTimetableLoader()
//  {
//  }
//..
// Then, we implement the 'load' function:
//..
//  // MANIPULATORS
//  int MyTimetableLoader::load(bdlt::Timetable *result,
//                              const char      *timetableName)
//  {
//..
// Next, we look up the timetable identified by 'timetableName' and load the
// corresponding text into a 'bsl::string' object, 'json' (as stated earlier,
// we do not specify in this example from where the timetable information is
// obtained):
//..
//      // Obtain the information for the timetable identified by
//      // 'timetableName' from an unspecified data source and load it into the
//      // 'json' string.
//
//      bsl::string json;
//
//      // Since a JSON parser is not available to 'bdlt', this example assumes
//      // that 'json' is populated with the following specific data:
//      //..
//      //  {
//      //      "firstDate":             "2018-01-01",
//      //      "lastDate":              "2018-12-31",
//      //      "initialTransitionCode": 1,
//      //      "transitions":
//      //        [
//      //          {
//      //            "datetime": "2018-05-28T09:00:00",
//      //            "code":     2
//      //          },
//      //          {
//      //            "datetime": "2018-05-28T18:00:00",
//      //            "code":     3
//      //          }
//      //        ]
//      //  }
//      //..
//      // Similarly, we hard-wire the value of a status flag, 'rc', to
//      // indicate that this string was successfully retrieved from the data
//      // source.
//
//      int rc = 0;  // success obtaining timetable information
//
//      if (rc != 0) {
//          return 1;                                                 // RETURN
//      }
//..
// Note that the non-zero value 1 is returned only in the case where the
// timetable information corresponding to 'timetableName' cannot be found (per
// the contract for the 'load' method).
//
// Then, we parse the "firstDate" and "lastDate" attributes from the 'json'
// string, loading the results into like-named variables:
//..
//      // Parse the "firstDate" and "lastDate" JSON attributes and load the
//      // results into 'firstDate' and 'lastDate', respectively.  It is an
//      // error if either of the "firstDate" or "lastDate" attributes are
//      // missing, or if they are out of order.
//
//      bdlt::Date firstDate;
//      bdlt::Date lastDate;
//
//      // For the purposes of this Usage, we hard-wire the first and last
//      // dates that are hypothetically parsed from the 'json' string, and
//      // set the 'rc' status flag indicating that parsing succeeded.
//
//      firstDate.setYearMonthDay(2018,  1,  1);
//      lastDate.setYearMonthDay( 2018, 12, 31);
//      rc = 0;  // success parsing "firstDate" and "lastDate" attributes
//
//      if (rc != 0 || firstDate > lastDate) {
//          return 2;                                                 // RETURN
//      }
//
//      result->reset();
//
//      result->setValidRange(firstDate, lastDate);
//..
// Next, we parse the "initialTransitionCode" attribute from 'json':
//..
//      // For the purposes of this Usage, we hard-wire a boolean flag
//      // indicating that the "initialTransitionCode" attribute was
//      // hypothetically detected in the 'json' string.
//
//      bool isInitialTransitionCodePresent = true;
//
//      if (isInitialTransitionCodePresent) {
//
//          // For the purposes of this Usage, we hard-wire the initial
//          // transition code that is hypothetically parsed from the 'json'
//          // string, and set the 'rc' status flag indicating that parsing
//          // succeeded.
//
//          int code = 1;
//
//          rc = 0;  // success parsing "initialTransitionCode" attribute
//
//          if (rc != 0) {
//              return 3;                                             // RETURN
//          }
//
//          result->setInitialTransitionCode(code);
//      }
//..
// Now, we parse the "transitions" attribute from 'json' and load the result
// into a 'bsl::vector<bsl::pair<bdlt::Datetime, int> >' object, 'transitions':
//..
//      // For the purposes of this Usage, we hard-wire a boolean flag
//      // indicating that the "transitions" attribute was hypothetically
//      // detected in the 'json' string.
//
//      bool isTransitionsPresent = true;
//
//      if (isTransitionsPresent) {
//
//          // Parse the "transitions" JSON attribute and load 'transitions'
//          // with the result.
//
//          bsl::vector<bsl::pair<bdlt::Datetime, int> > transitions;
//
//          // For the purposes of this Usage, we hard-wire the transitions
//          // that are hypothetically parsed from the 'json' string, and set
//          // the 'rc' status flag indicating that parsing succeeded.
//
//          transitions.push_back(bsl::pair<bdlt::Datetime, int>(
//                                        bdlt::Datetime(2018, 5, 28,  9), 2));
//          transitions.push_back(bsl::pair<bdlt::Datetime, int>(
//                                        bdlt::Datetime(2018, 5, 28, 18), 3));
//
//          rc = 0;  // success parsing "transitions" attribute
//
//          if (rc != 0) {
//              return 4;                                             // RETURN
//          }
//
//          bsl::vector<bsl::pair<bdlt::Datetime, int> >::const_iterator it =
//                                                         transitions.begin();
//
//          while (it != transitions.end()) {
//              const bdlt::Date& date = it->first.date();
//
//              if (date < firstDate || date > lastDate || -1 > it->second) {
//                  return 5;                                         // RETURN
//              }
//
//              result->addTransition(
//                             it->first,
//                             it->second >= 0
//                                 ? it->second
//                                 : bdlt::Timetable::k_UNSET_TRANSITION_CODE);
//
//              ++it;
//          }
//      }
//..
// Our timetable loader imposes the requirement that the dates specified in the
// "transitions" JSON attribute must be within the range
// '[firstDate .. lastDate]' and the transition codes are non-negative or
// unset.
//
// Finally, we return 0 indicating success:
//..
//      return 0;
//  }
//..

#include <bdlscm_version.h>

namespace BloombergLP {
namespace bdlt {

class Timetable;

                          // =====================
                          // class TimetableLoader
                          // =====================

class TimetableLoader {
    // This class defines a protocol used to load timetables from a specific
    // source.  Each repository of timetable information can be supported by a
    // distinct implementation of this protocol.

  public:
    // CREATORS
    virtual ~TimetableLoader();
        // Destroy this object.

    // MANIPULATORS
    virtual int load(Timetable *result, const char *timetableName) = 0;
        // Load, into the specified 'result', the timetable identified by the
        // specified 'timetableName'.  Return 0 on success, and a non-zero
        // value otherwise.  If the timetable corresponding to 'timetableName'
        // is not found, 1 is returned with no effect on '*result'.  If a
        // non-zero value other than 1 is returned (indicating a different
        // error), '*result' is valid, but its value is undefined.
};

}  // close package namespace
}  // close enterprise namespace

#endif

// ----------------------------------------------------------------------------
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
